﻿$ErrorActionPreference = 'Stop'
Set-PSDebug -Strict

function Select-LinkedWorkItems {
    param (
        [string]
        $LinkType,
        [string]
        $WorkItemType,
        [string]
        $State
    ) 
    process {
        $WorkItem = $_
        $WorkItem.WorkItemLinks |
    	Where-Object {
    		$_.LinkTypeEnd.ImmutableName -eq $LinkType -or
            $_.LinkTypeEnd.Name -eq $LinkType
    	} |
    	ForEach-Object {
    		$WorkItem.Store.GetWorkItem($_.TargetId)
    	} |
        Where-Object {
            -not $WorkItemType -or
            $_.Type.Name -eq $WorkItemType
        } |
        Where-Object {
            -not $State -or
            $_.State -eq $State
        }
    }
}

function Select-ChangedFields {
    param (
        [string]
        $Name,

        $OldValue,
        
        [object[]]
        $NewValue
    )
    process {
        $WorkItemChangedEvent = $_
        & {
            $WorkItemChangedEvent.CoreFields
            $WorkItemChangedEvent.ChangedFields
        } |
        ForEach-Object {
            $_.StringFields 
            $_.IntegerFields
        } |
        Where-Object {
            $_.NewValue -ne $_.OldValue
        } |
        Where-Object {
            -not $Name -or
            $_.Name -eq Name -or
            $_.ReferenceName -eq $Name
        } |
        Where-Object {
            -not $OldValue -or
            $_.OldValue -eq $OldValue
        } |
        Where-Object {
            -not $NewValue -or
            $NewValue -contains $_.NewValue
        }
    }
}

function Set-WorkItemState {
    param (
        [string]
        $State,
        [string]
        $Reason
    )
    process {
        $WorkItem = $_
        $WorkItem.State = $State
        if ($Reason) { $WorkItem.Reason = $Reason }
        if ($WorkItem.IsDirty) { $WorkItem.Save() }
    }
}

###

# map User Story Reasons to Task Reasons
$ReasonMap = @{
    Abandoned = 'Obsolete'
    Rejected= 'Cut'
    'Out of scope' = 'Deferred'
    'Code complete and unit tests pass' = 'Completed'
}

if ($WorkItemChangedEvent.ChangeType -eq 'Change') {

    if (
        $WorkItemChangedEvent |
            Select-ChangedFields -Name System.State -OldValue Active -NewValue Closed, Resolved
    ) {
        $WorkItem |
            Select-LinkedWorkItems -LinkType Child -WorkItemType Task -State Active |
            Set-WorkItemState -State Closed -Reason $ReasonMap[$WorkItem.Reason]
    }
}